﻿//
// ******************************************************************************************************************************
// WP-Framework
// 
// Developed by
// Lukas Kretschmar (lkretschmar.dev@bluewin.ch)
//
// Switzerland, Copyright (c) 2013 lkretschmar
// This content is released under the MIT License (http://opensource.org/licenses/MIT).
//     
// ******************************************************************************************************************************
//
//




using System.Reflection;
using System.Linq;
using System;
using System.Collections.Generic;

namespace KretschIT.WP_Fx.EasyMoq
{
    public sealed class Easy : BaseMockFactory
    {
        private static IDictionary<int, Easy> moqs = new Dictionary<int, Easy>();

        public static Easy Moq
        {
            get
            {
                var assembly = Assembly.GetCallingAssembly();
                return GetFactoryFor(assembly);
            }
        }

        private static Easy GetFactoryFor(Assembly assembly)
        {
            var hash = assembly.GetHashCode();
            if (!moqs.ContainsKey(hash))
            {
                AddNewFactoryFor(assembly, hash);
            }
            return moqs[hash];
        }

        private static void AddNewFactoryFor(Assembly assembly, int hash)
        {
            var factory = new Easy();
            moqs.Add(hash, factory);
            Setup(factory, assembly);
        }

        private Easy() { }

        private static void Setup(IMockFactoryRegistration factory, Assembly assembly)
        {
            var type = GetEasyMoqInitClass(assembly);
            if (type != null)
            {
                SetupRegistration(factory, type);
            }
        }

        private static Type GetEasyMoqInitClass(Assembly assembly)
        {
            var interfaceType = typeof(IEasyMoqRegistration);
            return assembly.GetTypes().SingleOrDefault(t => t.IsDefined(typeof(EasyMoqRegistrationAttribute), false) && interfaceType.IsAssignableFrom(t));
        }

        private static void SetupRegistration(IMockFactoryRegistration factory, Type type)
        {
            var registration = (IEasyMoqRegistration)Activator.CreateInstance(type);
            registration.Register(factory);
        }
    }
}
